using System;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;

namespace MovieDBReverseEngineering
{
    /// <summary>
    /// 演示如何使用EF Core上下文类进行数据库操作
    /// 包含艺人、电影和参与关系的增删改查示例
    /// </summary>
    class ContextOperationsDemo
    {
        static async Task Main(string[] args)
        {
            Console.WriteLine("电影数据库上下文类操作演示");
            Console.WriteLine("========================");
            
            // 获取数据库连接信息
            string connectionString = GetConnectionString();
            bool useMySql = GetDatabaseType();
            
            try
            {
                using (var dbOperations = new MovieDBContextOperations(connectionString, useMySql))
                {
                    // 测试数据库连接
                    await TestDatabaseConnection(dbOperations);
                    
                    // 演示菜单
                    bool exit = false;
                    while (!exit)
                    {
                        Console.Clear();
                        Console.WriteLine("电影数据库操作演示");
                        Console.WriteLine("================");
                        Console.WriteLine("1. 艺人管理操作");
                        Console.WriteLine("2. 电影管理操作");
                        Console.WriteLine("3. 参与关系管理操作");
                        Console.WriteLine("4. 数据查询演示");
                        Console.WriteLine(0 + ". 退出");
                        Console.WriteLine("================");
                        Console.Write("请选择操作: ");
                        
                        string choice = Console.ReadLine();
                        switch (choice)
                        {
                            case "1":
                                await DemonstrateArtistOperations(dbOperations);
                                break;
                            case "2":
                                await DemonstrateMovieOperations(dbOperations);
                                break;
                            case "3":
                                await DemonstrateParticipationOperations(dbOperations);
                                break;
                            case "4":
                                await DemonstrateQueries(dbOperations);
                                break;
                            case "0":
                                exit = true;
                                break;
                            default:
                                Console.WriteLine("无效的选择，请重试。");
                                break;
                        }
                        
                        if (!exit)
                        {
                            Console.WriteLine("按任意键继续...");
                            Console.ReadKey();
                        }
                    }
                }
                
                Console.WriteLine("演示结束！");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"发生错误: {ex.Message}");
                Console.WriteLine("演示程序终止。");
            }
            
            Console.WriteLine("按任意键退出...");
            Console.ReadKey();
        }

        /// <summary>
        /// 获取数据库连接字符串
        /// </summary>
        /// <returns>连接字符串</returns>
        private static string GetConnectionString()
        {
            Console.WriteLine("请输入数据库连接信息:");
            Console.Write("服务器地址 (默认: localhost): ");
            string server = Console.ReadLine();
            if (string.IsNullOrWhiteSpace(server))
            {
                server = "localhost";
            }
            
            Console.Write("数据库名称 (默认: MovieDB): ");
            string database = Console.ReadLine();
            if (string.IsNullOrWhiteSpace(database))
            {
                database = "MovieDB";
            }
            
            Console.Write("用户名 (默认: root): ");
            string userId = Console.ReadLine();
            if (string.IsNullOrWhiteSpace(userId))
            {
                userId = "root";
            }
            
            Console.Write("密码: ");
            string password = ReadPassword();
            
            Console.Write("端口号 (MySQL默认3306, SQL Server默认1433): ");
            string portStr = Console.ReadLine();
            int port = string.IsNullOrWhiteSpace(portStr) ? 0 : int.Parse(portStr);
            
            // 根据后续选择的数据库类型返回相应的连接字符串
            return "placeholder"; // 将在GetDatabaseType中重新生成
        }

        /// <summary>
        /// 选择数据库类型
        /// </summary>
        /// <returns>是否使用MySQL</returns>
        private static bool GetDatabaseType()
        {
            Console.WriteLine("请选择数据库类型:");
            Console.WriteLine("1. MySQL");
            Console.WriteLine("2. SQL Server");
            Console.Write("请选择: ");
            
            string choice = Console.ReadLine();
            
            // 重新构建连接字符串
            Console.Write("服务器地址 (默认: localhost): ");
            string server = Console.ReadLine();
            if (string.IsNullOrWhiteSpace(server))
            {
                server = "localhost";
            }
            
            Console.Write("数据库名称 (默认: MovieDB): ");
            string database = Console.ReadLine();
            if (string.IsNullOrWhiteSpace(database))
            {
                database = "MovieDB";
            }
            
            Console.Write("用户名 (默认: root/SQL Server使用Windows身份验证): ");
            string userId = Console.ReadLine();
            
            Console.Write("密码 (SQL Server使用Windows身份验证时留空): ");
            string password = ReadPassword();
            
            bool useMysql = choice == "1";
            
            if (useMysql)
            {
                Console.Write("端口号 (默认3306): ");
                string portStr = Console.ReadLine();
                int port = string.IsNullOrWhiteSpace(portStr) ? 3306 : int.Parse(portStr);
                
                // 设置MySQL连接字符串
                return true;
            }
            else
            {
                // SQL Server可以选择Windows身份验证或SQL Server身份验证
                bool useWindowsAuth = string.IsNullOrWhiteSpace(userId) || string.IsNullOrWhiteSpace(password);
                
                // 设置SQL Server连接字符串
                return false;
            }
        }

        /// <summary>
        /// 读取密码（不显示输入）
        /// </summary>
        /// <returns>密码字符串</returns>
        private static string ReadPassword()
        {
            string password = "";
            ConsoleKeyInfo key;
            
            do
            {
                key = Console.ReadKey(true);
                
                // 忽略Enter键，但处理退格键
                if (key.Key != ConsoleKey.Enter && key.Key != ConsoleKey.Backspace)
                {
                    password += key.KeyChar;
                    Console.Write("*");
                }
                else if (key.Key == ConsoleKey.Backspace && password.Length > 0)
                {
                    password = password.Substring(0, password.Length - 1);
                    Console.Write("\b \b");
                }
            }
            while (key.Key != ConsoleKey.Enter);
            
            Console.WriteLine();
            return password;
        }

        /// <summary>
        /// 测试数据库连接
        /// </summary>
        private static async Task TestDatabaseConnection(MovieDBContextOperations dbOperations)
        {
            try
            {
                Console.WriteLine("正在测试数据库连接...");
                // 使用一个简单的查询来测试连接
                await dbOperations.GetAllArtistsAsync();
                Console.WriteLine("数据库连接成功！");
            }
            catch (Exception ex)
            {
                Console.WriteLine($"数据库连接失败: {ex.Message}");
                throw;
            }
        }

        /// <summary>
        /// 演示艺人管理操作
        /// </summary>
        private static async Task DemonstrateArtistOperations(MovieDBContextOperations dbOperations)
        {
            Console.WriteLine("\n艺人管理操作演示");
            Console.WriteLine("================\n");
            
            // 1. 添加新艺人
            Console.WriteLine("1. 添加新艺人");
            Artist newArtist = new Artist
            {
                Name = "测试艺人",
                Birthday = DateTime.Parse("1990-01-01"),
                Sex = 'M',
                ImdbNumber = "nm1234567",
                Introduction = "这是一个测试艺人简介"
            };
            
            int artistId = await dbOperations.AddArtistAsync(newArtist);
            Console.WriteLine($"成功添加艺人，ID: {artistId}\n");
            
            // 2. 查询艺人
            Console.WriteLine("2. 查询艺人");
            Artist foundArtist = await dbOperations.GetArtistByIdAsync(artistId);
            if (foundArtist != null)
            {
                Console.WriteLine($"找到艺人: {foundArtist.Name}, 生日: {foundArtist.Birthday}");
            }
            
            // 3. 更新艺人信息
            Console.WriteLine("\n3. 更新艺人信息");
            foundArtist.Name = "测试艺人(已更新)";
            foundArtist.Introduction = "这是更新后的艺人简介";
            bool updated = await dbOperations.UpdateArtistAsync(foundArtist);
            Console.WriteLine(updated ? "艺人信息更新成功" : "艺人信息更新失败");
            
            // 4. 获取所有艺人
            Console.WriteLine("\n4. 获取所有艺人");
            var allArtists = await dbOperations.GetAllArtistsAsync();
            Console.WriteLine($"共有 {allArtists.Count} 个艺人:");
            foreach (var artist in allArtists.Take(5)) // 只显示前5个
            {
                Console.WriteLine($"- {artist.Name}");
            }
            
            // 5. 提示用户是否删除刚添加的艺人（清理演示数据）
            Console.WriteLine("\n5. 是否删除测试艺人? (y/n): ");
            if (Console.ReadKey().Key == ConsoleKey.Y)
            {
                await dbOperations.DeleteArtistAsync(artistId);
                Console.WriteLine("\n测试艺人已删除");
            }
            else
            {
                Console.WriteLine("\n测试艺人保留在数据库中");
            }
        }

        /// <summary>
        /// 演示电影管理操作
        /// </summary>
        private static async Task DemonstrateMovieOperations(MovieDBContextOperations dbOperations)
        {
            Console.WriteLine("\n电影管理操作演示");
            Console.WriteLine("================\n");
            
            // 1. 添加新电影
            Console.WriteLine("1. 添加新电影");
            Movie newMovie = new Movie
            {
                Name = "测试电影",
                ReleaseDate = DateTime.Parse("2023-01-01"),
                Duration = 120,
                Language = "中文",
                Introduction = "这是一个测试电影简介",
                Rating = 8.5f
            };
            
            int movieId = await dbOperations.AddMovieAsync(newMovie);
            Console.WriteLine($"成功添加电影，ID: {movieId}\n");
            
            // 2. 查询电影
            Console.WriteLine("2. 查询电影");
            Movie foundMovie = await dbOperations.GetMovieByIdAsync(movieId);
            if (foundMovie != null)
            {
                Console.WriteLine($"找到电影: {foundMovie.Name}, 上映日期: {foundMovie.ReleaseDate}, 评级: {foundMovie.Rating}");
            }
            
            // 3. 更新电影信息
            Console.WriteLine("\n3. 更新电影信息");
            foundMovie.Name = "测试电影(已更新)";
            foundMovie.Rating = 9.0f;
            bool updated = await dbOperations.UpdateMovieAsync(foundMovie);
            Console.WriteLine(updated ? "电影信息更新成功" : "电影信息更新失败");
            
            // 4. 获取所有电影
            Console.WriteLine("\n4. 获取所有电影");
            var allMovies = await dbOperations.GetAllMoviesAsync();
            Console.WriteLine($"共有 {allMovies.Count} 个电影:");
            foreach (var movie in allMovies.Take(5)) // 只显示前5个
            {
                Console.WriteLine($"- {movie.Name} (评级: {movie.Rating})");
            }
            
            // 5. 根据评级获取电影
            Console.WriteLine("\n5. 获取评级大于8.0的电影");
            var highRatedMovies = await dbOperations.GetMoviesByRatingAsync(8.0f);
            Console.WriteLine($"共有 {highRatedMovies.Count} 个高评级电影");
            
            // 6. 提示用户是否删除刚添加的电影（清理演示数据）
            Console.WriteLine("\n6. 是否删除测试电影? (y/n): ");
            if (Console.ReadKey().Key == ConsoleKey.Y)
            {
                await dbOperations.DeleteMovieAsync(movieId);
                Console.WriteLine("\n测试电影已删除");
            }
            else
            {
                Console.WriteLine("\n测试电影保留在数据库中");
            }
        }

        /// <summary>
        /// 演示参与关系管理操作
        /// </summary>
        private static async Task DemonstrateParticipationOperations(MovieDBContextOperations dbOperations)
        {
            Console.WriteLine("\n参与关系管理操作演示");
            Console.WriteLine("====================\n");
            
            // 首先添加测试艺人和电影
            Artist testArtist = new Artist
            {
                Name = "关系测试艺人",
                Birthday = DateTime.Parse("1985-05-15"),
                Sex = 'F',
                Introduction = "参与关系测试用艺人"
            };
            
            int artistId = await dbOperations.AddArtistAsync(testArtist);
            
            Movie testMovie = new Movie
            {
                Name = "关系测试电影",
                ReleaseDate = DateTime.Parse("2022-10-10"),
                Duration = 110,
                Language = "英文",
                Rating = 7.8f
            };
            
            int movieId = await dbOperations.AddMovieAsync(testMovie);
            
            Console.WriteLine($"已创建测试数据 - 艺人ID: {artistId}, 电影ID: {movieId}\n");
            
            // 1. 添加参与关系
            Console.WriteLine("1. 添加艺人参与电影关系");
            Participation participation = new Participation
            {
                ArtistId = artistId,
                MovieId = movieId,
                RoleName = "主角"
            };
            
            int participationId = await dbOperations.AddParticipationAsync(participation);
            Console.WriteLine($"成功添加参与关系，ID: {participationId}\n");
            
            // 2. 查询电影的演员
            Console.WriteLine("2. 查询电影的演员列表");
            var movieArtists = await dbOperations.GetArtistsByMovieAsync(movieId);
            Console.WriteLine($"电影 '{testMovie.Name}' 的演员:");
            foreach (var artist in movieArtists)
            {
                Console.WriteLine($"- {artist.Name}");
            }
            
            // 3. 查询艺人参演的电影
            Console.WriteLine("\n3. 查询艺人参演的电影列表");
            var artistMovies = await dbOperations.GetMoviesByArtistAsync(artistId);
            Console.WriteLine($"艺人 '{testArtist.Name}' 参演的电影:");
            foreach (var movie in artistMovies)
            {
                Console.WriteLine($"- {movie.Name}");
            }
            
            // 4. 删除参与关系
            Console.WriteLine("\n4. 删除参与关系");
            await dbOperations.DeleteParticipationAsync(participationId);
            Console.WriteLine("参与关系已删除");
            
            // 5. 清理测试数据
            Console.WriteLine("\n5. 清理测试数据");
            await dbOperations.DeleteMovieAsync(movieId);
            await dbOperations.DeleteArtistAsync(artistId);
            Console.WriteLine("测试数据已清理");
        }

        /// <summary>
        /// 演示数据查询功能
        /// </summary>
        private static async Task DemonstrateQueries(MovieDBContextOperations dbOperations)
        {
            Console.WriteLine("\n数据查询演示");
            Console.WriteLine("============\n");
            
            // 1. 查询所有艺人
            Console.WriteLine("1. 查询所有艺人");
            var artists = await dbOperations.GetAllArtistsAsync();
            Console.WriteLine($"总艺人数量: {artists.Count}");
            
            // 2. 查询所有电影
            Console.WriteLine("\n2. 查询所有电影");
            var movies = await dbOperations.GetAllMoviesAsync();
            Console.WriteLine($"总电影数量: {movies.Count}");
            
            // 3. 根据评级查询高评分电影
            Console.WriteLine("\n3. 查询高评分电影(评级>8.0)");
            var highRatedMovies = await dbOperations.GetMoviesByRatingAsync(8.0f);
            Console.WriteLine($"高评分电影数量: {highRatedMovies.Count}");
            foreach (var movie in highRatedMovies.Take(5))
            {
                Console.WriteLine($"- {movie.Name}: {movie.Rating} 分");
            }
            
            // 4. 如果有电影和艺人，展示一些关联查询示例
            if (movies.Count > 0 && artists.Count > 0)
            {
                int sampleMovieId = movies[0].Id;
                int sampleArtistId = artists[0].Id;
                
                Console.WriteLine($"\n4. 查询电影 ID {sampleMovieId} 的演员列表");
                var movieArtists = await dbOperations.GetArtistsByMovieAsync(sampleMovieId);
                Console.WriteLine($"该电影有 {movieArtists.Count} 个演员");
                
                Console.WriteLine($"\n5. 查询艺人 ID {sampleArtistId} 参演的电影");
                var artistMovies = await dbOperations.GetMoviesByArtistAsync(sampleArtistId);
                Console.WriteLine($"该艺人参演了 {artistMovies.Count} 部电影");
            }
            else
            {
                Console.WriteLine("\n数据库中没有足够的数据来演示关联查询，请先添加一些艺人和电影数据");
            }
        }
    }
}